<template>
  <el-row type="flex" justify="center">
    <el-col :span="7" style="min-width: 600px">
      <el-row type="flex" justify="center">
        <el-col>
          <el-card>
            <ProjectSelect :project-list="projects" @onSelect="projectSelect"></ProjectSelect>
          </el-card>
        </el-col>
      </el-row>
      <el-collapse-transition>
        <el-card shadow="always">
          <div v-if="currentProject" slot="header">
            <el-popover
              v-model="visible.addDoc"
              placement="bottom">
              <el-button slot="reference" size="small" icon="el-icon-plus" title="新建文档"></el-button>
              <el-input v-model="newDocName" placeholder="请输入文档名称"></el-input>
              <el-button @click="addDocument" style="width: 100%; margin-top: 10px" type="primary">保存</el-button>
            </el-popover>
            <el-button icon="el-icon-refresh" size="small" title="刷新列表" :loading="loading.refreshBtn" @click="loadDocuments(currentProject.id)"></el-button>
            <el-button @click="$router.push('/search')" style="float: right" icon="el-icon-search" title="去搜索" circle></el-button>
          </div>
          <DocumentList
            :default-page-size="5"
            pagination-layout="sizes, prev, pager, next"
            @onEdit="loadDocContent"
            @onRowChange="handleCurrentDocChange"
            v-if="currentProject"
            @onDelete="resetCurrentDoc"
            :project-id="currentProject.id"
          ></DocumentList>
          <div v-else>
            <el-tag type="warning">选择项目以查看文档列表</el-tag>
            <el-button @click="$router.push('/search')" style="float: right" icon="el-icon-search" title="去搜索" circle></el-button>
          </div>
        </el-card>
      </el-collapse-transition>
    </el-col>
    <el-col :span="11" style="min-width: 700px">
      <el-row type="flex" justify="center">
        <el-col>
          <el-collapse-transition>
            <el-card
              v-if="visible.editor">
              <div slot="header">
                <el-row>
                  <el-col>
                    <el-button-group style="float: left">
                      <el-button size="small" v-if="hasEditPermission" title="保存更改" @click="updateDocument" type="primary">保存</el-button>
                      <el-button size="small" :loading="loading.refreshSingleDocBtn" title="刷新文档" @click="reloadCurrentDocument">刷新</el-button>
                    </el-button-group>
                    <div style="float: right">
                      <el-dropdown @command="exportDocument">
                        <el-button title="导出文档" icon="el-icon-download" circle></el-button>
                        <el-dropdown-menu slot="dropdown">
                          <el-dropdown-item v-show="type.enable" v-for="type in supportedExportType" :command="type.type" v-bind:key="type.type">{{ type.desc }}</el-dropdown-item>
                        </el-dropdown-menu>
                      </el-dropdown>
                      <el-button @click="openDocSetting" icon="el-icon-setting" circle></el-button>
                    </div>
                  </el-col>
                </el-row>
              </div>
              <doc-editor
                :read-only="!hasEditPermission"
                :disabled="!currentDoc"
                v-loading="loading.editor"
                :value="docContent"
                @input="handleDocContentChange"></doc-editor>
            </el-card>
          </el-collapse-transition>
        </el-col>
      </el-row>
      <el-row type="flex" justify="center">
        <el-col>
          <el-collapse-transition>
            <el-card
              v-if="currentProject && currentDocId && visible.log">
              <div slot="header">
                <el-tag type="success">文档变更记录</el-tag>
                <el-tag title="文档版本" type="info" effect="plain" v-if="currentDoc">
                  <span>文档版本：</span>
                  <span class="log-tag-text">{{ currentDoc.version }}</span>
                </el-tag>
                <el-tag title="文档名称" type="info" effect="plain" v-if="currentDoc">
                  <span class="log-tag-text">{{ currentDoc.name }}</span>
                </el-tag>
                <el-tag title="文档创建者" type="info" effect="plain" v-if="currentDoc">
                  <span>文档作者：</span>
                  <span class="log-tag-text">{{ currentDoc.creatorId }}</span>
                </el-tag>
              </div>
              <DocumentLogsList :logs="docLogs"></DocumentLogsList>
            </el-card>
          </el-collapse-transition>
        </el-col>
      </el-row>
    </el-col>
    <el-drawer
      title="文档设置"
      :visible.sync="visible.docSetting">
      <el-row type="flex" justify="left" v-if="currentDoc && currentDocBackup" :gutter="12">
        <el-col :span="1"></el-col>
        <el-col :span="14">
          <el-input v-model="currentDocBackup.name" placeholder="输入新的文档名称">
            <template slot="prepend">文档名称</template>
          </el-input>
        </el-col>
        <el-col :span="3">
          <el-button type="primary" @click="updateDocName(currentDocBackup.name)">保存</el-button>
        </el-col>
      </el-row>
      <el-row type="flex" justify="left" v-if="currentDoc && currentDocBackup" :gutter="12" class="setting-item-margin">
        <el-col :span="1"></el-col>
        <el-col :span="14">
          <el-input v-model="currentDocBackup.url" placeholder="输入新的文档发布路径">
            <template slot="prepend">发布路径</template>
          </el-input>
        </el-col>
        <el-col :span="3">
          <el-button type="primary" @click="updateDocUrl(currentDocBackup.url)">保存</el-button>
        </el-col>
      </el-row>
      <el-row type="flex" justify="center" class="setting-item-margin">
        <el-col :span="22">
          <el-select
            v-model="currentDocEditPermission"
            title="更改文档编辑权限"
            :disabled="!hasUpdatePermission"
            @change="updateDocEditPermission"
            placeholder="选择编辑权限">
            <template slot="prefix">
              <span class="prefixSlot">编辑权限</span>
            </template>
            <el-option
              v-for="item in documentEditPermissionEnums"
              :key="item.code"
              :label="item.text"
              :value="item.code">
            </el-option>
          </el-select>
        </el-col>
      </el-row>
      <el-row type="flex" justify="center" class="setting-item-margin">
        <el-col :span="22">
          <el-select
            v-model="currentDocAccessPermission"
            title="更改文档访问权限"
            :disabled="!hasUpdatePermission"
            @change="updateDocAccessPermission"
            placeholder="选择访问权限">
            <template slot="prefix">
              <span class="prefixSlot">访问权限</span>
            </template>
            <el-option
              v-for="item in documentAccessPermissionEnum"
              :key="item.code"
              :label="item.text"
              :value="item.code">
            </el-option>
          </el-select>
        </el-col>
      </el-row>
      <el-row type="flex" justify="left" class="setting-item-margin">
        <el-col :span="1"></el-col>
        <el-col :span="15">
          <el-select
            v-model="currentDocTags"
            style="width: 100%"
            multiple
            filterable
            :allow-create="currentDocTags.length < 32"
            default-first-option
            @change="selectedTagChangeHandler"
            title="设置文档标签"
            :disabled="!hasUpdatePermission"
            placeholder="设置文档标签">
            <el-option
              v-for="item in defaultDocTags"
              :key="item.value"
              :label="item.label"
              :value="item.value">
            </el-option>
          </el-select>
        </el-col>
      </el-row>
    </el-drawer>
  </el-row>
</template>

<script>
// import 'tinymce/skins/content/default/content.css'
import ProjectSelect from '@/components/ProjectSelect'
import DocumentList from '@/components/DocumentList'
import DocumentLogsList from '@/components/DocumentLogsList'
import DocEditor from '@/components/DocEditor'
import {
  getTagsByDocId,
  addTag,
  removeTag
} from '@/api/docTag'
import {
  createFile,
  downloadFileToUser,
  getDocById,
  getDocInfoById,
  updateDoc,
  updateDocInfo,
  uploadFile
} from '@/api/document'
import tinymce from 'tinymce/tinymce'
import docEnum from '@/utils/docEnum'
export default {
  name: 'Document',
  components: {
    ProjectSelect,
    DocumentList,
    DocumentLogsList,
    DocEditor
  },
  created () {
    this.$store.dispatch('SetCurrentMenu', '文档库')
  },
  mounted () {
    if (this.projects.length === 0) {
      this.$store.dispatch('LoadProjects')
    }
    this.$store.commit('SET_DOCUMENTS', [])
    if (this.docLogs.length === 0) {
      this.$store.dispatch('LoadDocumentLogs', 3)
    }
  },
  data () {
    return {
      currentProject: undefined,
      currentDoc: undefined,
      currentPage: 1,
      pageSize: 10,
      docContent: undefined,
      loading: {
        editor: false,
        refreshBtn: false,
        refreshSingleDocBtn: false
      },
      visible: {
        editor: false,
        log: true,
        addDoc: false,
        docSetting: false
      },
      supportedExportType: [
        {
          type: 'txt',
          desc: '纯文本（*.txt）',
          enable: false
        },
        {
          type: 'pdf',
          desc: 'PDF文件（*.pdf）',
          enable: true
        },
        {
          type: 'html',
          desc: 'HTML文件（*.html）',
          enable: true
        }
      ],
      documentEditPermissionEnums: docEnum.DocumentEditPermissions,
      documentAccessPermissionEnum: docEnum.DocumentAccessPermissions,
      currentDocAccessPermission: '10',
      currentDocEditPermission: '00',
      currentExportType: 'pdf',
      newDocName: undefined,
      currentDocBackup: undefined,
      currentDocTags: [],
      defaultDocTags: [
        {
          value: '前端',
          label: '前端'
        },
        {
          value: '后端',
          label: '后端'
        },
        {
          value: '数据库',
          label: '数据库'
        }
      ],
      currentDocTagsCache: {}
    }
  },
  methods: {
    selectedTagChangeHandler (tags) {
      let cache = this.currentDocTagsCache
      let selectedTags = this.generateMap(tags)
      for (let key in cache) {
        // 如果原本有，现有的无，说明为删除模式
        if (!selectedTags[key]) {
          this.removeTagHandler(key, this.currentDoc.id)
          return
        }
      }
      for (let key in selectedTags) {
        // 如果原本无，现有的有，则说明为新增模式
        if (!cache[key]) {
          this.addTagHandler(key, this.currentDoc.id)
          return
        }
      }
    },
    generateMap (tags) {
      let tagMap = {}
      for (let i = 0; i < tags.length; i++) {
        tagMap[tags[i]] = tags[i]
      }
      return tagMap
    },
    removeTagHandler (tag, docId) {
      console.log('移除了: ' + JSON.stringify(tag))
      removeTag(docId, tag).then(() => {
        // 移除了一个tag，清除缓存
        delete this.currentDocTagsCache[tag]
        this.$message.success('移除成功')
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    addTagHandler (tag, docId) {
      console.log('新增了: ' + JSON.stringify(tag))
      addTag(docId, tag).then(() => {
        // 新增了一个tag，执行缓存
        this.currentDocTagsCache[tag] = tag
        this.$message.success('新增成功')
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    loadDocTags (docId) {
      if (!docId) {
        this.$notify.error('文档ID为空')
        return
      }
      getTagsByDocId(docId).then(res => {
        let tags = []
        for (let i = 0; i < res.data.length; i++) {
          let tag = res.data[i].tag
          tags.push(tag)
          this.currentDocTagsCache[tag] = tag
        }
        this.currentDocTags = tags
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    openDocSetting () {
      this.visible.docSetting = !this.visible.docSetting
      this.currentDocBackup = JSON.parse(JSON.stringify(this.currentDoc))
      this.loadDocTags(this.currentDocBackup.id)
    },
    loadDocContent (row) {
      this.visible.log = false
      setTimeout(() => {
        this.visible.editor = true
        this.loading.editor = true
        this.currentDoc = row
        this.currentDocAccessPermission = docEnum.DocumentAccessPermissionEnum[row.accessPermission].code
        this.currentDocEditPermission = docEnum.DocumentEditPermissionEnum[row.editPermission].code
        this.$store.commit('SET_DOCUMENT_LOGS', [])
        getDocById(this.currentProject.id, row.id).then(res => {
          setTimeout(() => {
            this.docContent = res
            this.loading.editor = false
          }, 500)
        }).catch(error => {
          setTimeout(() => {
            this.$notify.error(error)
            this.loading.editor = false
          }, 500)
        })
      }, 300)
    },
    updateDocAccessPermission (newVal) {
      let param = {
        projectId: this.currentProject.id,
        docId: this.currentDoc.id,
        formData: {
          version: this.currentDoc.version,
          id: this.currentDoc.id,
          accessPermission: newVal
        }
      }
      updateDocInfo(param).then(() => {
        this.reloadDocument(param.projectId, param.docId)
        this.$store.dispatch('LoadDocuments', param.projectId)
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    updateDocEditPermission (newVal) {
      let param = {
        projectId: this.currentProject.id,
        docId: this.currentDoc.id,
        formData: {
          version: this.currentDoc.version,
          id: this.currentDoc.id,
          editPermission: newVal
        }
      }
      updateDocInfo(param).then(() => {
        this.reloadDocument(param.projectId, param.docId)
        this.$store.dispatch('LoadDocuments', param.projectId)
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    updateDocName (newVal) {
      let param = {
        projectId: this.currentProject.id,
        docId: this.currentDoc.id,
        formData: {
          version: this.currentDoc.version,
          id: this.currentDoc.id,
          name: newVal
        }
      }
      updateDocInfo(param).then(() => {
        this.reloadDocument(param.projectId, param.docId)
        this.$store.dispatch('LoadDocuments', param.projectId)
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    updateDocUrl (newVal) {
      let param = {
        projectId: this.currentProject.id,
        docId: this.currentDoc.id,
        formData: {
          version: this.currentDoc.version,
          id: this.currentDoc.id,
          url: newVal
        }
      }
      updateDocInfo(param).then(() => {
        this.reloadDocument(param.projectId, param.docId)
        this.$store.dispatch('LoadDocuments', param.projectId)
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    handleDocContentChange (newVal) {
      this.docContent = newVal
      console.log(newVal)
    },
    handleCurrentDocChange (row) {
      this.currentDoc = row
      this.visible.editor = false
      setTimeout(() => {
        this.visible.log = true
      }, 300)
    },
    handleSizeChange (val) {
      this.pageSize = val
    },
    handleCurrentChange (val) {
      this.currentPage = val
    },
    rowSelect (row, col, event) {
      this.currentDoc = row
    },
    projectSelect (value) {
      this.currentProject = value
      this.visible.log = false
      this.visible.editor = false
    },
    exportDocument (exportType) {
      switch (exportType) {
        case 'pdf':
          tinymce.activeEditor.execCommand('mcePrint')
          break
        case 'txt':
          downloadFileToUser(this.docContent, this.currentDoc.name + '.txt')
          break
        case 'html':
          downloadFileToUser(this.docContent, this.currentDoc.name + '.html')
          break
        default:
          this.$notify.error('导出失败')
      }
    },
    updateDocument () {
      updateDoc({
        content: this.docContent,
        projectId: this.currentDoc.projectId,
        version: this.currentDoc.version,
        filename: this.currentDoc.name,
        docId: this.currentDoc.id
      }).then(() => {
        this.$notify.success('更新成功')
        this.reloadCurrentDocument()
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    addDocument () {
      if (!this.newDocName) {
        this.$notify.error('文档名称不能为空')
      }
      let file = createFile(this.newDocName, '')
      uploadFile(file, this.currentProject.id).then(() => {
        this.$notify.success('新建成功')
        this.$store.dispatch('LoadDocuments', this.currentProject.id)
        this.$set(this.visible, 'editor', false)
        this.$set(this.visible, 'log', false)
        this.$set(this.visible, 'addDoc', false)
        this.newDocName = undefined
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    loadDocuments (projectId) {
      this.loading.refreshBtn = true
      this.$store.dispatch('LoadDocuments', projectId).then(() => {
        setTimeout(() => {
          this.loading.refreshBtn = false
        }, 300)
      })
    },
    resetCurrentDoc (row) {
      if (!this.currentDoc) {
        return
      }
      if (row.id === this.currentDoc.id) {
        this.currentDoc = undefined
        this.docContent = undefined
        this.$store.commit('SET_CURRENT_DOC', undefined)
        this.$store.commit('SET_DOCUMENT_LOGS', [])
        this.visible.editor = false
        this.visible.log = false
      }
    },
    reloadDocument (projectId, docId) {
      getDocInfoById(projectId, docId).then(res => {
        this.currentDoc = res.data
        this.loadDocContent(res.data)
      }).catch(error => {
        this.$notify.error(error)
      })
    },
    reloadCurrentDocument () {
      this.loading.refreshSingleDocBtn = true
      this.reloadDocument(this.currentProject.id, this.currentDoc.id)
      setTimeout(() => {
        this.loading.refreshSingleDocBtn = false
      }, 300)
    }
  },
  computed: {
    documentName: function () {
      if (this.currentDoc === undefined) return 'nothing...'
      return this.currentProject.name + '/' + this.currentDoc.name
    },
    projects () {
      return this.$store.getters.projects
    },
    docLogs () {
      return this.$store.getters.documentLogs
    },
    currentDocId () {
      return this.$store.getters.currentDocId
    },
    disabledDownloadBtn () {
      return this.currentDoc === undefined || this.currentExportType === undefined
    },
    downloadBtnTitle () {
      if (!this.currentExportType) return '请选择导出格式'
      return '导出为 ' + this.currentExportType.toUpperCase()
    },
    hasUpdatePermission () {
      // 如果当前项目为空，返回false
      if (!this.$store.getters.currentProjectData) return false
      // 如果用户是项目创建者，返回true
      if (this.$store.getters.currentUserId === this.$store.getters.currentProjectData.creatorId) return true
      // 如果用户是文档创建者，返回true
      return this.$store.getters.currentUserId === this.currentDoc.creatorId
    },
    hasEditPermission () {
      // 如果当前项目为空，返回false
      if (!this.$store.getters.currentProjectData) return false
      // 如果当前文档为空，返回false
      if (!this.currentDoc) return false
      // 如果用户是文档创建者，返回true
      if (this.$store.getters.currentUserId === this.currentDoc.creatorId) return true
      // 如果用户是项目创建者，返回true
      if (this.$store.getters.currentUserId === this.$store.getters.currentProjectData.creatorId) return true
      // 如果是团队内可编辑，返回true
      let editPerm = this.currentDoc.editPermission
      return editPerm === docEnum.DocumentEditPermissionEnum.TEAM_ONLY.name
    }
  }
}
</script>

<style lang="scss" scoped>
.el-select >>> .el-input--prefix .el-input__inner {
  padding-left: 110px;
}
.prefixSlot {
  height: 36px;
  width: 90px;
  display: block;
  line-height: 36px;
  border-right: 1px solid #f1f1f1;
}
.el-card {
  border: 1px solid #d9dce2;
  margin: 7px;
}
.log-tag-text {
  font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
  font-weight: bolder;
}
.setting-item-margin {
  margin-top: 20px;
}
</style>
